home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / clang / tkern091.zip / SRC / PROCESS.C < prev    next >
Text File  |  1994-03-06  |  18KB  |  837 lines

  1. /*
  2.  *  This file forms part of "TKERN" - "Troy's Kernel for Windows".
  3.  *
  4.  *  Copyright (C) 1994  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /*
  22.  * This module handles task and process management.
  23.  *
  24.  * Tasks are Windows objects, identified by a task handle. Task handles
  25.  * can be reused without us waiting for them, so we can't use them to
  26.  * track parent-child relationships or to impliment the wait calls.
  27.  *
  28.  * Processes are tkern only objects which overcome these limitations.
  29.  * Every task is assigned a process number when it enters the system.
  30.  * When it leaves the system, if its parent is a tkern process, and
  31.  * it was created from tkern_exec, a zombie process is created, for which
  32.  * the parent mus wait.
  33.  */
  34.  
  35. #include <windows.h>
  36. #include <toolhelp.h>
  37. #include <stdlib.h>
  38. #include <memory.h>
  39. #include <string.h>
  40. #include <alloc.h>
  41. #include <stdarg.h>
  42. #include <errno.h>
  43. #include <sys/tfile.h>
  44. #include <sys/task.h>
  45. #include <sys/ioctl.h>
  46. #include <sys/wait.h>
  47. #include <sys/tkern.h>
  48.  
  49. struct    tk_process _process[N_TKPROCS];
  50. struct    tk_process _zombies[N_TKPROCS];
  51. struct    task    _tasks[TNTASK];
  52.  
  53. int    nTasks = 0;    // Doesn't count fledgelings
  54.  
  55. static    int    nProcesses = 0;
  56. static    int    nZombies = 0;
  57. static    struct    task    *ptNext = 0;
  58. static    struct    task    *ptParent = 0;
  59. static    HTASK        htaskParent = 0;
  60. static    short        pidParent = 0;
  61. static    short        pidChild = 0;
  62. static    short    pidCurrent;
  63. static    short    nPIDNext = 3;    // The first PID is 2, but that's fixed up
  64.                 // in WinMain.
  65.  
  66. static    void    task_is_dead(    int    iTask);
  67.  
  68. struct task *
  69. GetTaskInfo(void)
  70. {
  71.     HTASK    hTask;
  72.     int    i;
  73.  
  74.     hTask = GetCurrentTask();
  75.     for (i = 0; i < TNTASK; i++)
  76.     {
  77.         if (_tasks[i].hTask == hTask)
  78.         {
  79.             while (_tasks[i].iFledgeling != -1)
  80.                 i = _tasks[i].iFledgeling;
  81.             return &_tasks[i];
  82.         }
  83.     }
  84.     for (i = 0; i < TNTASK; i++)
  85.     {
  86.         if (!_tasks[i].hTask)
  87.         {
  88.             _tasks[i].hTask = hTask;
  89.             return &_tasks[i];
  90.         }
  91.     }
  92.     return 0;
  93. }
  94.  
  95. void
  96. inc_pid(short *pid)
  97. {
  98.     if (*pid == 32767)
  99.         *pid = 2;
  100.     else
  101.         (*pid)++;
  102. }
  103.  
  104.  
  105. /*
  106.  * aiExecErrors translates between WinExec errors and errno errors
  107.  */
  108.  
  109. static    int    aiExecErrors[] =
  110. {
  111.     ENOMEM,
  112.     EFAULT,
  113.     ENOENT,
  114.     ENOENT,
  115.     EFAULT,
  116.     ENOEXEC,
  117.     ENOEXEC,
  118.     EFAULT,
  119.     EFAULT,
  120.     EFAULT,
  121.     ENOEXEC,
  122.     ENOEXEC,
  123.     ENOEXEC,
  124.     ENOEXEC,
  125.     ENOEXEC,
  126.     ENOEXEC,
  127.     ETXTBSY,
  128.     ETXTBSY,
  129.     ENOEXEC,
  130.     EFAULT,
  131.     EFAULT,
  132.     EFAULT,
  133.     EFAULT,
  134.     EFAULT,
  135.     EFAULT,
  136.     EFAULT,
  137.     EFAULT,
  138.     EFAULT,
  139.     EFAULT,
  140.     EFAULT,
  141.     EFAULT,
  142.     EFAULT,
  143.     EFAULT
  144. };
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151. /* A normal POSIX exec would require pchPath, vaArgs and vaEnv.
  152.  * TKERN's also takes "pchCmdLine", the original command line.
  153.  * this is used by programs that don't use TKERN, and is the
  154.  * value used for WinExec, with pchPath prepended. If the program
  155.  * uses TKERN, it will call in to register, and then we tell it
  156.  * about its real arguments and environment.
  157.  *
  158.  * Yes, we inherit environment too.
  159.  */
  160.  
  161. short far _export
  162. tkern_exec(    char const    *pchPath,
  163.         va_list        vaArgs,
  164.         va_list        vaEnv,
  165.         char const    *pchCmdLine)
  166. {
  167.     struct    task *pt;
  168.     char    *pchCommand;
  169.     int    iNew;
  170.  
  171.     pt = GetTaskInfo();
  172.     if (pt->nFlags & TF_EXEC)    /* Attempt to recursively exec */
  173.     {
  174.         pt->nError = EAGAIN;
  175.         return -1;
  176.     }
  177.     pt->nFlags |= TF_EXEC;
  178.     Copy_Array(&pt->argv, (char **) vaArgs);
  179.     Copy_Array(&pt->envp, (char **) vaEnv);
  180.     pchCommand = (char *) malloc(strlen(pchPath) + strlen(pchCmdLine) + 2);
  181.     strcpy(pchCommand, pchPath);
  182.     if (pchCmdLine)
  183.     {
  184.         strcat(pchCommand, " ");
  185.         strcat(pchCommand, pchCmdLine);
  186.     }
  187.     while (ptNext)
  188.         GetMessages(pt); /* We only allow one exec at any one time */
  189.     ptNext = pt;
  190.     for (ptParent = pt;
  191.          ptParent->hTask == HTASK_FLEDGELING;
  192.          ptParent = _tasks + ptParent->iParent);
  193.     htaskParent = ptParent->hTask;
  194.     _tasks[pt->iParent].iFledgeling = -1;
  195.     pt->iParent = 0;    /* We don't keep this because the parent
  196.                  * may die.
  197.                  */
  198.     pidParent = ptParent->pid;
  199.     pidChild = 0;
  200.     if ((iNew = WinExec(pchCommand, SW_SHOW)) < 32)
  201.     {
  202.         ptParent->nError = aiExecErrors[iNew];
  203.         ptParent->iFledgeling = -1;
  204.         ptNext = 0;
  205.         task_is_dead(pt - _tasks);
  206.         htaskParent = 0;
  207.         pt->nFlags &= ~TF_EXEC;
  208.         pt->nError = ENOENT;
  209.         tkern_wakeup_call();
  210.         return -1;
  211.     }
  212.     free(pchCommand);
  213.     ptParent->nChildren++;
  214.     ptNext = 0;
  215.     htaskParent = 0;
  216.     tkern_wakeup_call();
  217.     pt->nFlags &= ~TF_EXEC;
  218.     if (pt->hTask == HTASK_FLEDGELING)
  219.     {
  220.         ptParent->iFledgeling = -1;
  221.         task_is_dead(pt - _tasks);
  222.     }
  223.     return pidChild;
  224. }
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  
  231. /*
  232.  * The three forms of wait.
  233.  *
  234.  * First, the original wait, which waits unconditionally until the child
  235.  * dies.
  236.  *
  237.  * Second, wait3, which takes flags. It is also supposed to return
  238.  * resource usage information but we don't keep that.
  239.  *
  240.  * Third, waitpid, the POSIX wait. This is to be preferred over wait3.
  241.  */
  242.  
  243. short far _export
  244. tkern_wait(union wait *wstatus)
  245. {
  246.     int    i;
  247.     short    pid;
  248.  
  249.     struct task *pt;
  250.     struct task *ptParent;
  251.  
  252.     pt = GetTaskInfo();
  253.  
  254.     /* Fledgelings cannot be parents */
  255.     for (ptParent = pt;
  256.          ptParent->hTask == HTASK_FLEDGELING;
  257.          ptParent = _tasks + ptParent->iParent);
  258.  
  259.     /* If the parent is childless, return immediately */
  260.     if (!ptParent->nChildren)
  261.         return 0;
  262.  
  263.     /* Wait until the parent has dead children */
  264.     while (!ptParent->nZombies)
  265.         GetMessages(pt);
  266.  
  267.     /* Reap the first dead child we encounter and return its pid */
  268.     for (i = 0; i < nZombies; i++)
  269.     {
  270.         if (_zombies[i].pidParent == ptParent->pid)
  271.         {
  272.             pid = _zombies[i].pid;
  273.             wstatus->w_status = 0;
  274.             wstatus->w_retcode = _zombies[i].nRetCode;
  275.             if (i < nZombies - 1)
  276.                 _zombies[i] = _zombies[nZombies - 1];
  277.             nZombies--;
  278.             ptParent->nZombies--;
  279.             ptParent->nChildren--;
  280.             return pid;
  281.         }
  282.     }
  283.     return 0;
  284. }
  285.  
  286.  
  287.  
  288.  
  289.  
  290. short far _export
  291. tkern_wait3(union wait *wstatus,
  292.         int    nFlags,
  293.         struct rusage *pZero)
  294. {
  295.     int    i;
  296.     short    pid;
  297.     struct task *pt;
  298.     struct task *ptParent;
  299.  
  300.     pt = GetTaskInfo();
  301.  
  302.     if (pZero)
  303.     {
  304.         pt->nError = EINVAL;
  305.         return -1;
  306.     }
  307.  
  308.     /* Fledgelings cannot be parents */
  309.     for (ptParent = pt;
  310.          ptParent->hTask == HTASK_FLEDGELING;
  311.          ptParent = _tasks + ptParent->iParent);
  312.  
  313.     /* If the parent is childless, return immediately */
  314.     if (!ptParent->nChildren)
  315.         return 0;
  316.  
  317.     /* If the WNOHANG flag is supplied, and there are no
  318.      * zombies, return immediately
  319.      */
  320.     if (!ptParent->nZombies && (nFlags & WNOHANG))
  321.         return 0;
  322.  
  323.     /* Since we don't have BSD jobs, we can't use WUNTRACED */
  324.  
  325.     /* Wait until the parent has dead children */
  326.     while (!ptParent->nZombies)
  327.         GetMessages(pt);
  328.  
  329.     /* Reap the first dead child we encounter and return its pid */
  330.     for (i = 0; i < nZombies; i++)
  331.     {
  332.         if (_zombies[i].pidParent == ptParent->pid)
  333.         {
  334.             pid = _zombies[i].pid;
  335.             wstatus->w_status = 0;
  336.             wstatus->w_retcode = _zombies[i].nRetCode;
  337.             if (i < nZombies - 1)
  338.                 _zombies[i] = _zombies[nZombies - 1];
  339.             nZombies--;
  340.             ptParent->nZombies--;
  341.             ptParent->nChildren--;
  342.             return pid;
  343.         }
  344.     }
  345.     return 0;
  346. }
  347.  
  348.  
  349.  
  350.  
  351.  
  352. short far _export
  353. tkern_waitpid(    int    pid,
  354.         union wait *wstatus,
  355.         int    nFlags)
  356. {
  357.     int    i;
  358.     struct task *pt;
  359.     struct task *ptParent;
  360.     BOOL    bZombie;
  361.     int    iEntry;
  362.     struct tk_process *pProc;
  363.     int    nLastZombies = -1;
  364.  
  365.     pt = GetTaskInfo();
  366.  
  367.     /* Fledgelings cannot be parents */
  368.     for (ptParent = pt;
  369.          ptParent->hTask == HTASK_FLEDGELING;
  370.          ptParent = _tasks + ptParent->iParent);
  371.  
  372.     /* If the parent is childless, return immediately */
  373.     if (!ptParent->nChildren)
  374.         return 0;
  375.  
  376.     while (1)
  377.     {
  378.         /* Find the process entry for this child */
  379.         if (pid)
  380.         {
  381.             if (ptParent->nZombies != nLastZombies)
  382.             {
  383.                 iEntry = -1;
  384.                 for (i = 0;  iEntry == -1 && i < nProcesses; i++)
  385.                 {
  386.                     if (_process[i].pid == pid)
  387.                     {
  388.                         iEntry = i;
  389.                         bZombie = FALSE;
  390.                         pProc = &_process[i];
  391.                     }
  392.                 }
  393.                 for (i = 0; iEntry == -1 && i < nZombies; i++)
  394.                 {
  395.                     if (_zombies[i].pid == pid)
  396.                     {
  397.                         iEntry = i;
  398.                         bZombie = TRUE;
  399.                         pProc = &_zombies[i];
  400.                     }
  401.                 }
  402.                 if (pProc->pidParent != ptParent->pid)
  403.                 {
  404.                     pt->nError = EACCES;
  405.                     return -1;
  406.                 }
  407.                 nLastZombies = ptParent->nZombies;
  408.                 if (iEntry == -1)
  409.                 {
  410.                     pt->nError = EFAULT;
  411.                     return -1;
  412.                 }
  413.                 if (!bZombie && (nFlags & WNOHANG))
  414.                     return 0;
  415.                 if (bZombie)
  416.                 {
  417.                     wstatus->w_status = 0;
  418.                     wstatus->w_retcode = _zombies[iEntry].nRetCode;
  419.                     nZombies--;
  420.                     if (iEntry < nZombies)
  421.                         _zombies[i] = _zombies[nZombies];
  422.                     ptParent->nZombies--;
  423.                     ptParent->nChildren--;
  424.                     return pid;
  425.                 }
  426.             }
  427.             else if (!ptParent->nZombies && (nFlags & WNOHANG))
  428.             {
  429.                 return 0;
  430.             }
  431.         }
  432.         else if (ptParent->nZombies)
  433.         {
  434.             for (i = 0; i < nZombies; i++)
  435.             {
  436.                 if (_zombies[i].pidParent == ptParent->pid)
  437.                 {
  438.                     pid = _zombies[i].pid;
  439.                     wstatus->w_status = 0;
  440.                     wstatus->w_retcode = _zombies[i].nRetCode;
  441.                     if (i < nZombies - 1)
  442.                         _zombies[i] = _zombies[nZombies - 1];
  443.                     nZombies--;
  444.                     ptParent->nZombies--;
  445.                     ptParent->nChildren--;
  446.                     return pid;
  447.                 }
  448.             }
  449.         }
  450.         else if (nFlags & WNOHANG)
  451.         {
  452.             return 0;
  453.         }
  454.  
  455.         /* Wait until the parent has dead children */
  456.         GetMessages(pt);
  457.     }
  458. }
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466. /* tkern_fork only handles the internal (to tkern) part of fork().
  467.  * the Throw/Catch functions must be handled in the child program.
  468.  * consequently, fork is represented as a macro.
  469.  */
  470.  
  471. int far _export
  472. tkern_fork(void)
  473. {
  474.     struct    task *pt;
  475.     int    i, j;
  476.  
  477.     pt = GetTaskInfo();
  478.     for (i = 0; i < TNTASK; i++)
  479.     {
  480.         if (!_tasks[i].hTask)
  481.             break;
  482.     }
  483.     if (i == TNTASK)
  484.     {
  485.         pt->nError = ENOMEM;
  486.         return -1;
  487.     }
  488.     pt->iFledgeling = i;
  489.     _tasks[i].hTask = HTASK_FLEDGELING;
  490.     _tasks[i].iParent = (pt - _tasks);
  491.     memcpy(_tasks[i].files, pt->files, sizeof(_tasks[i].files));
  492.     for (j = 0; j < UFILE_MAX; j++)
  493.     {
  494.         if (_tasks[i].files[j] != -1)
  495.             _files[_tasks[i].files[j]].tf_cnt++;
  496.     }
  497.     return 0; /* When we return, we are in the "child" process */
  498. }
  499.  
  500.  
  501. int far _export
  502. tkern_total_zombies(void)
  503. {
  504.     return nZombies;
  505. }
  506.  
  507. int far _export
  508. tkern_list_zombies(    struct tk_process *pList,
  509.             int    nEntries)
  510. {
  511.  
  512.     if (nZombies < nEntries)
  513.         nEntries = nZombies;
  514.     memcpy(pList, _zombies, sizeof(*pList) * nEntries);
  515.     return nEntries;
  516. }
  517.  
  518. /* Note that because tkern_get_process takes an HTASK, it can
  519.  * only return an active process, not a zombied one
  520.  */
  521. int far _export
  522. tkern_get_process(    HTASK    hTask,
  523.             struct    tk_process *tk_proc)
  524. {
  525.     int    i;
  526.  
  527.     for (i = 0; i < nProcesses; i++)
  528.     {
  529.         if (_process[i].hTask == hTask)
  530.         {
  531.             *tk_proc = _process[i];
  532.             return _process[i].pid;
  533.         }
  534.     }
  535.     return 0;
  536. }
  537.  
  538.  
  539.  
  540.  
  541. void far _export
  542. tkern_register_program(    int    *argc,
  543.             char    ***argv,
  544.             char    ***envp)
  545. {
  546.     int    i;
  547.     struct task *pt;
  548.     TASKENTRY te;
  549.  
  550.     TaskFindHandle(&te, GetCurrentTask());
  551.     if (htaskParent &&
  552.         (!te.hTaskParent ||
  553.          htaskParent == te.hTaskParent))
  554.     {
  555.         /* Because of the way tkern_exec() is written,
  556.          * the only way this can be true is if this
  557.          * is the task spawned from the tkern_exec()
  558.          */
  559.         pt = ptNext;
  560.         pt->hTask = GetCurrentTask();
  561.         for (i = 0; pt->argv[i]; i++);
  562.         *argc = i;
  563.         *argv = pt->argv;
  564.         *envp = pt->envp;
  565.         pt->pid = pidCurrent;
  566.     }
  567.     else
  568.     {
  569.         pt = GetTaskInfo();
  570.         if (pt->argv)
  571.         {
  572.             for (i = 0; *pt->argv; i++);
  573.             *argc = i;
  574.             *argv = pt->argv;
  575.             *envp = pt->envp;
  576.         }
  577.         else
  578.         {
  579.             *argc = 0;
  580.             *argv = 0;
  581.             *envp = 0;
  582.         }
  583.         pt->pid = pidCurrent;
  584.     }
  585.  
  586.     /* We need to flush all messages in the first task because if
  587.      * that task exits without having yielded, TKFMANGR will miss
  588.      * the exit notification.
  589.      */
  590.     if (!nTasks)
  591.         FlushMessages();
  592.     nTasks++;
  593.     while (!hwndManager)
  594.         GetMessages(pt);
  595. }
  596.  
  597. static    void
  598. task_is_dead(    int    iTask)
  599. {
  600.     int    iFile;
  601.  
  602.     if (_tasks[iTask].iFledgeling != -1)
  603.         task_is_dead(_tasks[iTask].iFledgeling);
  604.     for (iFile = 0; iFile < UFILE_MAX; iFile++)
  605.         if (_tasks[iTask].files[iFile] != -1)
  606.             internal_close(iFile, iTask);
  607.     if (_tasks[iTask].argv)
  608.     {
  609.         free(_tasks[iTask].argv);
  610.         _tasks[iTask].argv = 0;
  611.     }
  612.     if (_tasks[iTask].envp)
  613.     {
  614.         free(_tasks[iTask].envp);
  615.         _tasks[iTask].envp = 0;
  616.     }
  617.     _tasks[iTask].hTask = 0;
  618. }
  619.  
  620. #pragma argsused
  621. void    far    _export
  622. tkern_program_started(HTASK    htaskNew)
  623. {
  624.     short    iEntry, i;
  625.     short    nPID;
  626.     BOOL    bOK;
  627.  
  628.     if (nProcesses == N_TKPROCS) // Should be impossible
  629.         return;    // Well what else can we do?
  630.     iEntry = nProcesses++;
  631.     do
  632.     {
  633.         nPID = nPIDNext;
  634.         bOK = TRUE;
  635.         for (i = 0; i < nProcesses; i++)
  636.         {
  637.             if (_process[i].pid == nPID)
  638.             {
  639.                 bOK = FALSE;
  640.                 break;
  641.             }
  642.         }
  643.         if (bOK)
  644.         {
  645.             for (i = 0; i < nZombies; i++)
  646.             {
  647.                 if (_zombies[i].pid == nPID)
  648.                 {
  649.                     bOK = FALSE;
  650.                     break;
  651.                 }
  652.             }
  653.         }
  654.         inc_pid(&nPIDNext);
  655.     } while (!bOK);
  656.     _process[iEntry].pid = nPID;
  657.     _process[iEntry].hTask = htaskNew;
  658.     if (ptNext && !pidChild)
  659.     {
  660.         _process[iEntry].pidParent = pidParent;
  661.         _process[iEntry].hTaskParent = htaskParent;
  662.         pidChild = nPID;
  663.         _process[iEntry].iParent = ptParent - _tasks;
  664.     }
  665.     else
  666.     {
  667.         _process[iEntry].pidParent = 1;
  668.         _process[iEntry].hTaskParent = 0;
  669.         _process[iEntry].iParent = -1;
  670.     }
  671.     pidCurrent = nPID;
  672. }
  673.  
  674. void    far    _export
  675. tkern_program_dead(    HTASK    htaskCorpse,
  676.             int    nRetCode)
  677. {
  678.     int    i;
  679.     short    nPID = 0;
  680.  
  681.     /* First, clean up the tkern data on the task, along with
  682.      * all open files.
  683.      */
  684.  
  685.     /* MessageBox(0, "Phew. Has somebody died in here?", 0, MB_OK); */
  686.     for (i = 0; i < TNTASK; i++)
  687.     {
  688.         if (_tasks[i].hTask == htaskCorpse)
  689.         {
  690.             task_is_dead(i);
  691.             nTasks--;
  692.             if (!nTasks)
  693.                 SendMessage(hwndManager, TKWM_ALLDONE, 0, 0);
  694.             break;
  695.         }
  696.     }
  697.  
  698.     /* Next, look for any children, and the process itself, in the process
  699.      * list.
  700.      */
  701.     for (i = 0; i < nProcesses; i++)
  702.     {
  703.         /* Change any orphaned processes to pidParent = 1, hTaskParent = 0 */
  704.         if (_process[i].hTaskParent == htaskCorpse)
  705.         {
  706.             /* A process has become orphaned */
  707.             _process[i].hTaskParent = 0;
  708.             _process[i].pidParent = 1;
  709.             _process[i].iParent = -1;
  710.         }
  711.  
  712.         if (_process[i].hTask == htaskCorpse)
  713.         {
  714.             /* This is the process entry for this task */
  715.             nPID = _process[i].pid;
  716.  
  717.             /* If there is room in the zombies table, and the process
  718.              * has a living parent, copy the process entry to the zombies
  719.              * table, and issue a wakeup call for any processes waiting
  720.              * for children.
  721.              *
  722.              * note that if the process has no parents, failing to copy
  723.              * it to the zombie table automatically causes it to be reaped.
  724.              */
  725.             if (nZombies < N_TKPROCS && _process[i].iParent != -1)
  726.             {
  727.                 _zombies[nZombies] = _process[i];
  728.                 _zombies[nZombies].nRetCode = nRetCode;
  729.                 _tasks[_process[i].iParent].nZombies++;
  730.                 nZombies++;
  731.                 tkern_wakeup_call();
  732.             }
  733.  
  734.             nProcesses--;
  735.             if (i != nProcesses)
  736.             {
  737.                 _process[i] = _process[nProcesses];
  738.                 i--;
  739.             }
  740.         }
  741.     }
  742.  
  743.     /* Search for any zombie children of the current process and reap them */
  744.     for (i = 0; i < nZombies; i++)
  745.     {
  746.         if (_zombies[i].pidParent == nPID)
  747.         {
  748.             nZombies--;
  749.             if (i != nZombies)
  750.             {
  751.                 _zombies[i] = _zombies[nZombies];
  752.                 i--;
  753.             }
  754.         }
  755.     }
  756. }
  757.  
  758.  
  759. void
  760. process_init(void)
  761. {
  762.     TASKENTRY te;
  763.     HTASK    htaskNow;
  764.     int    i, j;
  765.  
  766.     for (i = 0; i < TNTASK; i++)
  767.     {
  768.         _tasks[i].hTask = 0;
  769.         _tasks[i].argv = 0;
  770.         _tasks[i].envp = 0;
  771.         _tasks[i].pid = 0;
  772.         _tasks[i].nChildren = 0;
  773.         _tasks[i].nZombies = 0;
  774.         _tasks[i].iFledgeling = -1;
  775.         for (j = 0; j < UFILE_MAX; j++)
  776.             _tasks[i].files[j] = -1;
  777.     }
  778.     htaskNow = GetCurrentTask();
  779.     te.dwSize = sizeof(TASKENTRY);
  780.     TaskFirst(&te);
  781.     memset(_process, 0, sizeof(_process));
  782.     memset(_zombies, 0, sizeof(_zombies));
  783.     do
  784.     {
  785.         if (htaskNow == te.hTask)
  786.             pidCurrent = nPIDNext;
  787.         _process[nProcesses].pid = nPIDNext++;
  788.         _process[nProcesses].pidParent = 1;
  789.         _process[nProcesses].hTaskParent = 0;
  790.         _process[nProcesses].hTask = te.hTask;
  791.         _process[nProcesses].iParent = -1;
  792.         nProcesses++;
  793.     } while (TaskNext(&te));
  794. }
  795.  
  796.  
  797. int far _export
  798. tkern_kill(    int    pid,
  799.         int    nSignal)
  800. {
  801.     int    i;
  802.     struct    task *pt;
  803.  
  804.     pt = GetTaskInfo();
  805.  
  806.     for (i = 0; i < nProcesses; i++)
  807.     {
  808.         if (_process[i].pid == pid)
  809.         {
  810.             switch(nSignal)
  811.             {
  812.             case 0:
  813.                 break;
  814.             case 1:
  815.             case 2:
  816.             case 9:
  817.             case 14:
  818.                 TerminateApp(_process[i].hTask, NO_UAE_BOX);
  819.                 break;
  820.  
  821.             default:
  822.                 TerminateApp(_process[i].hTask, UAE_BOX);
  823.                 break;
  824.             }
  825.             return 0;
  826.         }
  827.     }
  828.     for (i = 0; i < nZombies; i++)
  829.     {
  830.         if (_process[i].pid == pid)
  831.             return 0;    /* Can't kill the undead */
  832.     }
  833.     pt = GetTaskInfo();
  834.     pt->nError = EFAULT;
  835.     return -1;
  836. }
  837.